# @Desc: 发行商品
import random
import time

from django.db import IntegrityError, transaction

from account.models import Members
from account.trade import get_member_goods
from libs.common import success, error, rand_str
from libs.form import RawJsonForm
from trade.exceptions.my_exception import MyException
from trade.models.goods import Goods

# 创建商品
from trade.models.goods_alloc_logs import GoodsAllocLogs
from trade.models.member_goods import MemberGoods
from trade.models.member_goods_logs import MemberGoodsLogs


def create_goods(request):
    form = RawJsonForm(request.body)
    symbol = form.get('symbol')
    member_id = form.get('member_id')
    title = form.get('title')
    amount = form.get_int('amount')
    stocks = form.get_int('stocks')
    total = form.get_int('total')
    price = form.get_int('price')

    now = int(time.time())
    goods = Goods()
    goods.member_id = member_id
    goods.sn = symbol
    goods.title = title
    goods.amount = amount
    goods.total = total
    goods.stocks = stocks
    goods.price = price
    goods.status = 1
    goods.updated = now
    goods.created = now
    try:
        goods.save()
    except IntegrityError as err:
        err_msg = "商品添加失败"
        if err.args[0] == 1062:
            err_msg = "商品编号或名称已经存在"
        return error(err_msg)
    if goods is not None and goods.id > 0:
        return success()
    else:
        return error()


'''
分配商品
allocate_data = [{"member_id": 1, "amount": 500}]
'''


def batch_allocate_goods(request):
    form = RawJsonForm(request.body)
    symbol = form.get('symbol')
    allocate_method = form.get('allocate_method')
    if allocate_method == 1:  # 指定数量
        amount = form.get_int('amount')
        allocate_data = form.get('allocate_data')
        err = batch_allocate_goods_by_amount(symbol, amount, allocate_data)
        if err is not None:
            return error(err)

    return success()


# 获取商品库存、标题
def get_goods(symbol):
    goods = Goods.objects.filter(sn=symbol).values('id', 'sn', 'title', 'stocks', 'ver').get()
    return goods


def add_goods_for_member(symbol, allocate_data, batch_mark=''):
    err = None
    try:
        db_goods_dict = get_goods(symbol)
        with transaction.atomic():
            symbol = db_goods_dict.get('sn')
            title = db_goods_dict.get('title')
            goods_ver = db_goods_dict.get('ver')
            now = int(time.time())

            member_id = allocate_data.get('member_id')
            amount = allocate_data.get('amount')
            db_mem_data = get_member_goods(member_id, symbol)

            if db_mem_data is None:
                member_goods = MemberGoods()
                member_goods.goods_sn = symbol
                member_goods.member_id = member_id
                member_goods.title = title
                member_goods.amount = amount
                member_goods.updated = now
                member_goods.created = now
                member_goods.save()
                amount_prev = 0
                amount_next = amount
            else:
                mem_goods_id = db_mem_data.get('id')
                ver = db_mem_data.get('ver')
                amount_prev = db_mem_data.get('amount')
                amount_next = amount_prev + amount
                new_mem_goods = {
                    'amount': amount_next,
                    'ver': ver + 1
                }
                MemberGoods.objects.filter(id=mem_goods_id, ver=ver).update(**new_mem_goods)

            goods_stocks_prev = db_goods_dict.get('stocks')
            goods_stocks_next = goods_stocks_prev - amount
            if goods_stocks_next > 0:
                new_goods_data = {
                    'stocks': goods_stocks_next,
                    'ver': goods_ver + 1
                }
                affected = Goods.objects.filter(sn=symbol, ver=goods_ver).update(**new_goods_data)
                if affected == 0:
                    raise MyException("更新商品库存失败")
            else:
                raise MyException("商品库存数量不足")

            goods_alloc_logs = GoodsAllocLogs()
            goods_alloc_logs.goods_sn = symbol
            goods_alloc_logs.to_member_id = member_id
            goods_alloc_logs.amount = amount
            goods_alloc_logs.stocks_prev = goods_stocks_prev
            goods_alloc_logs.stocks_next = goods_stocks_next
            goods_alloc_logs.created = now
            goods_alloc_logs.save()

            member_goods_logs = MemberGoodsLogs()
            member_goods_logs.member_id = member_id
            member_goods_logs.goods_sn = symbol
            member_goods_logs.subject_type = 1
            member_goods_logs.subject_sn = ''
            member_goods_logs.trade_type = 3
            member_goods_logs.amount = amount
            member_goods_logs.amount_prev = amount_prev
            member_goods_logs.amount_next = amount_next
            member_goods_logs.batch_mark = batch_mark
            member_goods_logs.created = now
            member_goods_logs.save()

    except MyException as my_ex:
        err = my_ex
    except Exception as ex:
        print('为会员添加商品', ex)
        err = "增加商品数量失败"
    return err


def add_goods_for_members(symbol, allocate_data_arr):
    err = None
    batch_mark = rand_str(8, 1)
    for allocate_data in allocate_data_arr:
        err = add_goods_for_member(symbol, allocate_data, batch_mark)
    return err


def batch_allocate_goods_by_amount(symbol, default_amount, allocate_data_arr):
    try:
        if type(allocate_data_arr) is not list:
            return "分配数据错误"
        allocate_total = 0
        for item in allocate_data_arr:
            if 'amount' in item and item.get('amount') > 0:
                allocate_total += item.get('amount')
            else:
                allocate_total += default_amount
                item['amount'] = default_amount
        if allocate_total <= 0:
            return "分配数量无效"
        db_goods_dict = get_goods(symbol)
        goods_stocks = db_goods_dict.get('stocks')
        if goods_stocks is None:
            return "商品不存在或无库存"
        if goods_stocks < allocate_total:
            return "商品库存不足"
        err = add_goods_for_members(symbol, allocate_data_arr)
    except Exception as ex:
        print(ex)
        err = "分配失败"
    return err


def get_rand_airdrops(money, num):
    if money < num:
        return None
    choice = random.sample(range(1, money), num - 1)
    choice.extend([0, money])
    choice.sort()
    return [(choice[i + 1] - choice[i]) for i in range(num)]


def airdrops(request):
    form = RawJsonForm(request.body)
    symbol = form.get('symbol')
    amount = form.get_int('amount')
    if amount <= 0:
        return error('无效的空投数量')
    try:
        db_goods = get_goods(symbol)
    except Exception as ex:
        print(ex)
        return error('商品不存在')
    num = Members.objects.filter(deleted=0).count()
    if num == 0:
        return error('无会员数据')
    if db_goods.get('stocks') < amount:
        return error('空投数量超过商品库存数量')
    airdrop_allocate_list = get_rand_airdrops(amount, num)
    if airdrop_allocate_list is None:
        return error('商品数量不足以空投')
    db_members = Members.objects.filter(deleted=0).all()
    i = 0
    batch_mark = rand_str(8, 1)
    for mem in db_members:
        item = {
            'member_id': mem.id,
            'amount': airdrop_allocate_list[i]
        }
        i += 1
        err = add_goods_for_member(symbol, item, batch_mark)
        if err is not None:
            print(err)

    return success()
